let http = require('http')
let https = require('https')
let urllib = require('url')
let assert = require('assert')

// 设计一个http和https通用的请求库
function requestUrl(url, headers) {
    let urlObj = urllib.parse(url)
    let httpMod = null
    if (urlObj.protocol == 'http:') {
        httpMod = http
    } else if (urlObj.protocol == 'https:') {
        httpMod = https
    } else {
        throw new Error(`无法识别协议,${urlObj.protocol}`)
    }

    return new Promise((resolve, reject) => {
        // http.request -> option可以是一个url地址字符串, 可以是一个json参数
        // 以下这种以json传参的方法跟直接传url的方式返回结果一样, http.request('http://www.taobao.com/)
        let req = httpMod.request({
            host: urlObj.host,
            path: urlObj.path,
            // 重要
            headers
        }, res => {
            let arr = []
            // 304代表是缓存
            if (res.statusCode == 200 && res.statusCode < 300 || res.statusCode === 304){
                res.on('data', data => {
                    arr.push(data)
                })
                res.on('end', () => {
                    let buffer = Buffer.concat(arr)
                    resolve({
                        statusCode: 200,
                        body:       buffer,
                        headers:    res.headers
                    })
                })
            } else if (res.statusCode == 301 || res.statusCode == 302) {
                // location -> https://www.taobao.com/
                resolve({
                    statusCode: res.statusCode,
                    body:       null,
                    headers:    res.headers
                })
            } else {
                reject({
                    statusCode: res.statusCode,
                    body:       null,
                    headers:    res.headers
                })
            }
        })

        req.on('error', err => {
            console.log(err)
        })

        req.write('')

        req.end()
    })
}

async function request(url, reqHeaders) {
    try {
        while (1) {
            let {statusCode, body, headers} = await requestUrl(url, reqHeaders)
            console.log(statusCode, url)
            if (statusCode == 200) {
                return {body, headers}
            } else {
                assert(statusCode==301 || statusCode==302)
                assert(headers.location)

                url = headers.location
            }
        }
    } catch(e) {
        console.log(e)
    }
}

module.exports = request